/*
 *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you under the Apache License, Version 2.0 (the
 *   "License"); you may not use this file except in compliance
 *   with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing,
 *   software distributed under the License is distributed on an
 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *   KIND, either express or implied.  See the License for the
 *   specific language governing permissions and limitations
 *   under the License.
 *
 */

package org.apache.directory.mavibot.btree;

import java.io.File;
import java.io.FileWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;

import org.apache.directory.mavibot.btree.serializer.LongSerializer;

/**
 * This main is called to run multiple thread which will insert elements in a persistedBtree.
 * The first argument of the main is used by an other main.
 * The second argument correspond to the cache size
 * The third argument correspond to the number of thread which will run
 * The last argument correspond to a name which will use to create two files.
 * The first will contain the sum of insert for each thread.
 * The second will contain the VM memory used by the thread during the execution.
 * 
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 *
 */
public class BenchMarchInsertValue {
	public static void main( String[] args ) throws Exception
	{
		if( args.length!=5 )
		{
			System.out.println( "wrong number of arguments" );
			return;
		}

		List<Tuple<Long, Long>> sortedTuple = new ArrayList<Tuple<Long, Long>>();
		File file = File.createTempFile( "managedbtreebuilder", ".data" );
	    file.deleteOnExit();

	    RecordManager rm = new RecordManager( file.getAbsolutePath() );

	    LongSerializer ser = new LongSerializer();
	    PersistedBTreeBuilder<Long, Long> bb = new PersistedBTreeBuilder<Long, Long>( rm, "master", 4, ser,
	        ser );
	    
	    MBeanServerConnection mBeanServerConnection = ManagementFactory.getPlatformMBeanServer();
	    ObjectName objThread = mBeanServerConnection.queryNames( new ObjectName( "java.lang:type=Memory" ), null ).iterator().next();
	    MemoryMXBean memoryMXBean = JMX.newMXBeanProxy( mBeanServerConnection, objThread, java.lang.management.MemoryMXBean.class,false );
	    MemoryUsage mhu= memoryMXBean.getHeapMemoryUsage();
	    
		int cacheSize=Integer.parseInt( args[1] );
		int nbThread = Integer.parseInt( args[2] );
		Long duration = Long.parseLong( args[3] );
		PersistedBTree<Long, Long> btree = ( PersistedBTree<Long, Long> ) bb.build( sortedTuple.iterator() );
		final CountDownLatch latch = new CountDownLatch( nbThread );
		ArrayList<MyThreadTest> tabThreads = new ArrayList<MyThreadTest>();
		MyThreadTest mythreadTemp;
		for(long i=0;i<cacheSize;i++)
		{
			btree.insert(i, i);
		}
		long nbBytesBegin=mhu.getUsed();
		for ( int i = 0; i < nbThread; i++ )
		{
			mythreadTemp = new MyThreadTest( latch, i, btree, duration,
					cacheSize );
			tabThreads.add( mythreadTemp );
			mythreadTemp.start();
		}
		latch.await();
		mhu= memoryMXBean.getHeapMemoryUsage();
		long nbBytesEnd=mhu.getUsed();
		FileWriter myFileWriter=new FileWriter( args[4], true );
		FileWriter myFileWriterCacheMemory=new FileWriter( "VmMemory"+args[4], true );
		Long numberCacheAccess=0L;
		for ( MyThreadTest thread : tabThreads )
		{
			numberCacheAccess+=thread.getTab().get( thread.getTab().size()-1 ).getNbInsertion();
		}
		myFileWriter.write( String.valueOf( numberCacheAccess )+"\n" );
		myFileWriterCacheMemory.write( String.valueOf( nbBytesEnd-nbBytesBegin )+"\n" );
		myFileWriter.close();
		myFileWriterCacheMemory.close();
	}
}